import React, {CSSProperties} from "react";
import {Input, TreeSelect as AntdTreeSelect, Form as AntdForm,} from 'antd';
import {VJsonComponent} from "../../factory";
import _ from 'lodash'
import {YvanEvent} from "../../types";
import {apply, YvanEventBind, YvanEventDispatch} from "../../utils/helper";
import {DataComponentProp} from "../../datasource";
import {FormItemBaseState, FormItemVJSon, VJsonFormItemBase} from "./VJsonFormItemBase";
import * as Extend from '../../extend'
import {toJS} from "mobx";

export interface TreeSelectVJsonProp extends FormItemVJSon<TreeSelect> {
    addonAfter?: string | React.ReactNode
    addonBefore?: string | React.ReactNode
    //支持清除
    allowClear?: boolean
    //默认获取焦点	boolean	false
    autoFocus?: boolean
    //是否有边框	boolean	true
    bordered?: boolean
    //当此项为 true 时，点选每级菜单选项值都会发生变化	boolean	false
    changeOnSelect?: boolean
    //是否默认展开下拉菜单	boolean	-
    defaultOpen?: boolean
    //指定默认选中的条目	string[] | number[]
    defaultValue?: string[] | number[]
    //是否禁用	boolean	false
    disabled?: boolean
    //次级菜单的展开方式，可选 'click' 和 'hover'
    expandTrigger?: 'click' | 'hover'
    //当下拉列表为空时显示的内容
    notFoundContent?: string
    //自定义浮层类名
    popupClassName?: string
    //浮层预设位置：bottomLeft bottomRight topLeft topRight 默认bottomLeft
    popupPlacement?: 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight'
    //控制浮层显隐
    popupVisible?: boolean
    //在选择框中显示搜索框 默认 false
    showSearch?: boolean
    //选择框默认文字	string	-
    placeholder?: string
    //选择框大小
    size?: 'large' | 'middle' | 'small'
    treeDefaultExpandAll: boolean
    dataType?: 'tree' | '';

    // 选中 option，或 input 的 value 变化时，调用此函数	function(value, option:Option | Array<Option>)	-
    onChange?: YvanEvent<TreeSelect>
    // 	显示/隐藏浮层的回调 (value) => void
    onPopupVisibleChange?: YvanEvent<TreeSelect>
}

export interface TreeSelectVJsonDataProp extends TreeSelectVJsonProp, DataComponentProp<TreeSelect> {

}

export interface TreeSelectState extends FormItemBaseState<TreeSelect> {
    dataType?: 'tree' | '';
}

@VJsonComponent({
    view: 'treeSelect'
})
//@ts-ignore
export default class TreeSelect extends VJsonFormItemBase<TreeSelect, TreeSelectVJsonDataProp, TreeSelectState> {
    static defaultProps = {
        ...VJsonFormItemBase.defaultProps,
        allowClear: true,
        idField: 'value',
        labelField: 'label',
        parentField: 'parentValue',
        childrenField: 'children',
        changeOnSelect: false,
        treeDefaultExpandAll: false,
        dataType: '',
        data: [],
        rules: [],
        visible: true,
        valueSpliter: '/'
    }

    constructor(props: any) {
        super(props, TreeSelect.defaultProps);

        if (this.valueIsArray()) {
            this.defaultValue = this.valueSplit(this.defaultValue)
        }
    }

    private valueSplit(value?: string | string[]) {
        return value;
    }

    private valueJoin(value?: string | string[]) {
        return value
    }

    private valueIsArray() {
        return (this.props.vjson.mode === 'multiple' || this.props.vjson.mode === 'tags')
    }

    getTreeData() {
        if (this.props.vjson.dataType === 'tree') {
            return toJS(this.data)
        }
        const _data: any[] = [];
        const idNodeMap: any = {};
        const idKey = this.props.vjson.idField || 'value';
        const labelKey = this.props.vjson.labelField || 'label';
        const parentIdKey = this.props.vjson.parentField || 'parentValue';

        _.forEach(toJS(this.data), (item, index) => {
            const id = item[idKey]
            idNodeMap[id] = {
                value: '' + item[idKey],
                title: item[labelKey] ? item[labelKey] : '',
                parentId: item[parentIdKey] ? item[parentIdKey] : '',
            }
        })
        _.forEach(idNodeMap, (node) => {
            if (idNodeMap[node.parentId]) {
                // 存在父级元素
                const children = idNodeMap[node.parentId].children;
                if (!children || !_.isArray(children)) {
                    idNodeMap[node.parentId].children = [node];
                } else {
                    children.push(node)
                }

            } else {
                _data.push(node);
            }
        })
        return _data;
    }


    protected onValueChange(value: any) {
        value = this.valueJoin(value)
        if (value !== this.value) {
            this.value = value
            YvanEventDispatch(this.props.vjson.onChange, this, value)
        }
    }

    /**
     * 从控件值到实体 (control -> entity) 的转换 normalizeToEntity
     */
    normalizeToEntity(value: any) {
        if (this.valueIsArray()) {
            return this.valueJoin(value)
        }
        return value
    }

    /**
     * 从实体值到控件 (entity -> control) 的转换 normalizeToEntity
     */
    normalizeToControl(value: any) {
        if (this.valueIsArray()) {
            return this.valueSplit(value)
        } else {
            return this.valueJoin(value)
        }
    }

    protected get _isRootFormItem() {
        return false
    }

    protected renderWrapper(): JSX.Element {
        if (Extend.isDebugMode()) {
            console.log('RenderSelect', this.toString())
        }

        const fieldOption = {
            label: this.props.vjson.labelField,
            value: this.props.vjson.idField,
            children: this.props.vjson.childrenField,
        }

        const addonAfter =
            (typeof this.props.vjson.addonAfter === 'undefined')
                ? null
                : (<span className="ant-input-group-addon">
                        {
                            apply(this, this.props.vjson.addonAfter)
                        }
                </span>)

        return (
            <span className="ant-input-group-wrapper">
                <span className="ant-input-wrapper ant-input-group">
                    <AntdForm.Item noStyle
                                   {...this._getFormItemBindProperty(false)}
                    >
                        {/*@ts-ignore*/}
                        <AntdTreeSelect key={this.key} view_id={this.key} aria-roledescription={this.view}
                                        showSearch={true}
                            // filterOption={this._filterOption.bind(this)}
                                        treeData={this.getTreeData()}
                                        allowClear={apply(this, this.props.vjson.allowClear)}
                                        autoFocus={apply(this, this.props.vjson.autoFocus)}
                                        bordered={apply(this, this.props.vjson.bordered)}
                                        changeOnSelect={this.props.vjson.changeOnSelect}
                                        disabled={apply(this, this.props.vjson.disabled)}
                                        style={toJS(this.props.vjson.style)}
                                        loading={this.loading}
                                        treeDefaultExpandAll={this.props.vjson.treeDefaultExpandAll}
                                        onBlur={YvanEventBind(this.props.vjson.onBlur, this)}
                                        onChange={this.onValueChange.bind(this)}
                                        onPopupVisibleChange={YvanEventBind(this.props.vjson.onPopupVisibleChange, this)}
                                        onFocus={YvanEventBind(this.props.vjson.onFocus, this)}
                                        onInputKeyDown={YvanEventBind(this.props.vjson.onInputKeyDown, this)}
                                        onMouseEnter={YvanEventBind(this.props.vjson.onMouseEnter, this)}
                                        onMouseLeave={YvanEventBind(this.props.vjson.onMouseLeave, this)}
                                        onSelect={YvanEventBind(this.props.vjson.onSelect, this)}
                                        displayRender={label => {
                                            if (_.isArray(label)) {
                                                return label.join(this.props.vjson.valueSpliter)
                                            }
                                            return label
                                        }}
                                        open={this.props.vjson.open}
                                        placeholder={apply(this, this.props.vjson.placeholder)}
                                        fieldNames={fieldOption}
                                        size={apply(this, this.props.vjson.size)}
                        >
                        </AntdTreeSelect>
                    </AntdForm.Item>
                    {
                        addonAfter
                    }
                </span>
            </span>
        )
    }
}
